EncodePointer / DecodePointer functions for KERNEL32.DLL in Windows XP/2003#

kernel32-obfuscated-pointers

Purpose/History#

These functions are used by Windows Applications to make memory pointers more secure.

The EncodePointer / DecodePointer code used originally comes from Wine:
https://github.com/rpodgorny/wine/blob/master/libs/port/interlocked.c
https://github.com/wine-mirror/wine/blob/master/dlls/ntdll/rtl.c

Here is a essay about these functions https://devblogs.microsoft.com/oldnewthing/20201113-00/?p=104447:

Requirements#

  1. A x86 version of Windows 2003 / XP SP1 with source code available: see https://rentry.co/build-win2k3
  2. Ability to execute executables built for newer versions than Windows XP SP2 / Windows Server 2003 RTM (NT 5.2): https://rentry.co/kernel32-version-unlock

Changes#

  1. change \base\win32\client\baseinit.c: add the following block
__declspec(naked) void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare )
{
    __asm mov eax, 12[esp];
    __asm mov ecx, 8[esp];
    __asm mov edx, 4[esp];
    __asm lock cmpxchg [edx], ecx;
    __asm ret;
}

static DWORD_PTR get_pointer_obfuscator( void )
{
    static DWORD_PTR pointer_obfuscator;

    if (!pointer_obfuscator)
    {
        ULONG seed = NtGetTickCount();
        ULONG_PTR rand;

        /* generate a random value for the obfuscator */
        rand = RtlUniform( &seed );

        /* handle 64bit pointers */
        rand ^= RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);

        /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
        rand |= 0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);

        interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator, (void*) rand, NULL );
    }

    return pointer_obfuscator;
}

/*************************************************************************
 * RtlEncodePointer   [NTDLL.@]
 */
PVOID WINAPI EncodePointer(
  IN PVOID Ptr
)
{
    DWORD_PTR ptrval = (DWORD_PTR) Ptr;
    return (PVOID)(ptrval ^ get_pointer_obfuscator());
}

PVOID WINAPI DecodePointer(
   PVOID Ptr
)
{
    DWORD_PTR ptrval = (DWORD_PTR) Ptr;
    return (PVOID)(ptrval ^ get_pointer_obfuscator());
}
  1. In \base\win32\client\kernel32.src: add these two lines
    DecodePointer
    EncodePointer
    
  2. Run bcz (not bz as it will not add the two functions to KERNEL32.DLL)
  3. Overwrite the created \base\win32\client\daytona\obj\i386\KERNEL32.DLL in the C:\WINDOWS\SYSTEM32 folder of your Windows XP installation.
Edit
Pub: Nov 13 2020 17:53 UTC
Edit: Nov 13 2020 20:25 UTC
Views: 64